package com.sino.dataworks.job;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dataworks_public.model.v20200518.GetInstanceStatusCountRequest;
import com.aliyuncs.dataworks_public.model.v20200518.GetInstanceStatusCountResponse;
import com.aliyuncs.dataworks_public.model.v20200518.ListInstancesRequest;
import com.aliyuncs.dataworks_public.model.v20200518.ListInstancesResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.utils.StringUtils;
import com.sino.dataworks.dto.InstanceEntityDto;
import com.sino.dataworks.dto.PhoneWarnDto;
import com.sino.dataworks.dto.StatusCountDto;
import com.sino.dataworks.enums.DataWorksTaskStatus;
import com.sino.dataworks.util.DataworksUtil;
import com.sino.dataworks.util.JobVarUtil;
import com.sino.dataworks.util.TimeCheckUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.springframework.beans.BeanUtils;

import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.LocalTime;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import static com.sino.dataworks.util.JobVarUtil.*;

@Slf4j
public class DataworksPhoneWarningTask implements Job {

    static IAcsClient client = null;
    Map<String, String> warningMap = new HashMap<>();

    static {
        String endPoint = System.getenv("ALIBABA_END_POINT");
        String regionId = System.getenv("ALIBABA_REGION_ID");
        if (StringUtils.isEmpty(endPoint)) {
            endPoint = "dataworks-public-vpc.res.cloud.cheryfs.cn";
        }
        String keyId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
        String keySec = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
        if (StringUtils.isEmpty(keyId)) {
            keyId = "ZR18OFackif3jKT7";
        }
        if (StringUtils.isEmpty(keySec)) {
            keySec = "Pfvaw2BOmDPC4zEu1UglDu87jCn5yi";
        }
        if (StringUtils.isEmpty(regionId)) {
            regionId = "cn-wuhu-qrhy-d01";
        }
        DefaultProfile profile = DefaultProfile.getProfile(
                regionId,
                keyId, // 替换为你的AccessKey ID
                keySec); // 替换为你的AccessKey Secret
        DefaultProfile.addEndpoint(regionId, "dataworks-public", endPoint);
        client = new DefaultAcsClient(profile);
    }

//    @Override
//    public void execute(JobExecutionContext jobExecutionContext)  {
//        Date newDate = DateUtil.offset(new Date(), DateField.DAY_OF_MONTH, -1);
////        boolean isFirstWarning = JobVarUtil.isFirstWarning;
////        boolean isNeedWarning = JobVarUtil.isNeedWarning;
////        Date begin = JobVarUtil.begin;
////        Map<String,InstanceEntityDto> hasRerunMap=JobVarUtil.hasRerunMap;
////        Map<String,InstanceEntityDto> hasWarningMap=JobVarUtil.hasWarningMap;
////        Map<String,Integer> retryMap=JobVarUtil.retryMap;
//        log.info("是否报警"+isNeedWarning);
//
//        try {
//                LocalTime now = LocalTime.now();
//                int currentHour = now.getHour();
//                int currentMinute = now.getMinute();
//                StatusCountDto statusCountDto = getStatusCount();
//                log.info("当前时间：" +DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")+ "当前小时：" + currentHour +" "+currentMinute+ " " + JSON.toJSONString(statusCountDto));
//                    if (statusCountDto.getFailureCount() > 0) {
//                        String bizDate = DateUtil.format(newDate, "yyyy-MM-dd");
//                        String endTime = DateUtil.format(new Date(), "yyyy-MM-dd");
//                       List<InstanceEntityDto> dtos= DataworksUtil.getInstance(DataWorksTaskStatus.FAILURE.getCode(),bizDate,endTime);
//                       if (dtos.size()>0){
//                           log.info("跑批有任务失败");
//                           List<InstanceEntityDto> needReRun=new ArrayList<>();
//                           List<InstanceEntityDto> dtoss=new ArrayList<>();
//                           for (InstanceEntityDto dto:dtos){
//                               if(!hasWarningMap.containsKey(dto.getNodeName())){
//                                   dtoss.add(dto);
//                               }else {
//                                   log.info("已告过警："+dto.getNodeName()+"-不再告警");
//                               }
//                           }
//                           for (InstanceEntityDto dto:dtoss){
//                                  log.info("节点名称:"+dto.getNodeName());
//                                 retryMap.put(dto.getNodeName(),retryMap.getOrDefault(dto.getNodeName(),0)+1);
//                                   if(dto.getNodeName().equals("back_oracle_check_file")||dto.getNodeName().equals("back_oracle_qdata_check_file")){
//                                       retryMap.put(dto.getNodeName(),retryMap.getOrDefault(dto.getNodeName(),0));
//                                       if(!hasRerunMap.containsKey(dto.getNodeName())){
//                                           DataworksUtil.phoneWarning("数据中台备库数据导入出现问题");
//                                       }
//                                       hasRerunMap.put(dto.getNodeName(),dto);
//                                   }
//                                   if(!hasRerunMap.containsKey(dto.getNodeName())){
//                                       if(dto.getNodeName().equals("back_oracle_check_file")||dto.getNodeName().equals("back_oracle_qdata_check_file")){
//                                           DataworksUtil.phoneWarning("数据中台备库数据导入出现问题");
//                                           hasRerunMap.put(dto.getNodeName(),dto);
//                                       }else{
//                                           needReRun.add(dto);
//                                       }
//                                   }else {
//                                       if(retryMap.get(dto.getNodeName())>=5){
//                                           log.info("已经重跑过4次："+dto.getNodeName());
//                                           hasWarningMap.put(dto.getNodeName(),dto);
//                                           isNeedWarning=true;
//                                       }else{
//                                           if(dto.getNodeName().equals("back_oracle_check_file")||dto.getNodeName().equals("back_oracle_qdata_check_file")){
//                                               log.info("已报警");
//                                           }else{
//                                               needReRun.add(dto);
//                                           }
//                                       }
//                                   }
//                           }
//                           if (needReRun.size()>0){
//                               hasRerunMap.putAll(DataworksUtil.reRun(needReRun));
//                           }
//                       }
//                      if(isNeedWarning){
//                           if (isFirstWarning) {
//                               isFirstWarning = false;
//                               begin = DateUtil.date();
//                               log.info("跑批任务有失败!电话告警");
//                               DataworksUtil.phoneWarning(null);
//                               isNeedWarning=false;
//                           } else {
//                               //30分钟后依然还有错误 继续电话告警
//                               Date end = DateUtil.date();
//                               long minutes = DateUtil.between(begin, end, DateUnit.MINUTE);
//                               if (minutes > 30) {
//                                   log.info("跑批任务有失败!电话告警");
//                                   DataworksUtil.phoneWarning(null);
//                                   begin =  DateUtil.date();
//                                   isNeedWarning=false;
//                               }
//                           }
//                       }
//                    }else {
//                        isNeedWarning=false;
//                    }
//                    String cuur=currentHour+":"+currentMinute;
//                    if(cuur.equals("3:0")){
//                        log.info("当前未运行数量:"+statusCountDto.getNotRunCount());
//                        if(statusCountDto.getNotRunCount()>= JobVarUtil.notRunNum){
//                            log.info("未运行数量:"+statusCountDto.getNotRunCount());
//                            DataworksUtil.phoneWarning("三点数据中台未运行数量为"+statusCountDto.getNotRunCount()+"大于"+JobVarUtil.notRunNum+"个");
//                        }
//                    }
//                if(currentHour>6){
//                    String ff=String.valueOf(currentHour)+String.valueOf(currentMinute);
//                    log.info("清空缓存"+ff);
//                    hasRerunMap.clear();
//                    hasWarningMap.clear();
//                    retryMap.clear();
//                    begin=null;
//                    isFirstWarning=true;
//                    isNeedWarning=false;
//                }
//        } catch (Exception e) {
//            Date end = DateUtil.date();
//            long minutes = DateUtil.between(begin, end, DateUnit.MINUTE);
//            if (minutes > 30) {
//                log.info("发生异常!电话告警");
//                DataworksUtil.phoneWarning(null);
//                begin =  DateUtil.date();
//                isNeedWarning=false;
//            }
//            log.info(e.getMessage());
//            e.printStackTrace();
//        }
//    }

    @Override
    public void execute(JobExecutionContext jobExecutionContext)  {
        Date newDate = DateUtil.offset(new Date(), DateField.DAY_OF_MONTH, -1);
        String bizDate = DateUtil.format(newDate, "yyyy-MM-dd");
        String endTime = DateUtil.format(new Date(), "yyyy-MM-dd");
        List<String> oracleScript=new ArrayList<>();
        List<InstanceEntityDto> dtos=new ArrayList<>();
        try {
            oracleScript = Files.lines(Paths.get("back_oracle.txt")).collect(Collectors.toList());
            LocalTime now = LocalTime.now();
            int currentHour = now.getHour();
            int currentMinute = now.getMinute();
            StatusCountDto statusCountDto = getStatusCount();
            log.info("当前时间：" +DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")+ "当前小时：" + currentHour +" "+currentMinute+ " " + JSON.toJSONString(statusCountDto));
            List<PhoneWarnDto> phoneWarnDtos= new ArrayList<>();
            if (statusCountDto.getFailureCount() > 0) {
                 dtos= new ArrayList<>();
                //if(statusCountDto.getFailureCount()<=100){
                    dtos= DataworksUtil.getInstance(DataWorksTaskStatus.FAILURE.getCode(),bizDate,endTime);
              //  }else {
                  //  for (int i=1;i<=statusCountDto.getFailureCount();i++){
                 //       dtos.addAll(DataworksUtil.getErrorInstance(DataWorksTaskStatus.FAILURE.getCode(),bizDate,endTime,i,100));
                 //   }
              //  }
                if (dtos.size()>0){
                    log.info("跑批有任务失败");
                    List<InstanceEntityDto> needReRun=new ArrayList<>();
                    for (InstanceEntityDto dto:dtos){
                        log.info("节点名称:"+dto.getNodeName());
                        String errorLog=DataworksUtil.getInstanceLog(DataworksUtil.getInstancesByNodeId(String.valueOf(dto.getNodeId())).get(0).getInstanceId());
                        //生产表不存在 自动提交表到生产环境
                        List<String> tableNames=  DataworksUtil.parseLogForTableNotFound(errorLog);
                        if(tableNames!=null&&tableNames.size()>0){
                            for (String tableName:tableNames){
                                DataworksUtil.submitTable(tableName.replace("datawarehouse_pro.",""));
                            }
                        }
                        retryMap.put(dto.getNodeName(),retryMap.getOrDefault(dto.getNodeName(),0)+1);
                        if(!phoneWarnDtoMap.containsKey(dto.getNodeName())){
                            PhoneWarnDto phoneWarnDto=new PhoneWarnDto();
                            BeanUtils.copyProperties(dto,phoneWarnDto);
                            phoneWarnDto.setFirstErrorTime(new Date());
                            phoneWarnDto.setFirstWarn(true);
                            phoneWarnDto.setSecondWarn(true);
                            phoneWarnDtoMap.put(dto.getNodeName(),phoneWarnDto);
                        }
                        if(oracleScript.contains(dto.getNodeName())){
                            if(!phoneWarnDtoMap.containsKey(dto.getNodeName())){
                                PhoneWarnDto phoneWarnDto=new PhoneWarnDto();
                                BeanUtils.copyProperties(dto,phoneWarnDto);
                                phoneWarnDto.setFirstErrorTime(new Date());
                                phoneWarnDto.setFirstWarnTime(new Date());
                                phoneWarnDto.setFirstWarn(true);
                                phoneWarnDto.setSecondWarn(true);
                                phoneWarnDtoMap.put(dto.getNodeName(),phoneWarnDto);
                                DataworksUtil.phoneWarning("数据中台备库数据导入出现问题");
                            }
                        }
                        if(retryMap.get(dto.getNodeName())>=5){
                            log.info("节点跑批失败："+dto.getNodeName());
                            PhoneWarnDto phoneWarnDto=phoneWarnDtoMap.get(dto.getNodeName());
                            if(!phoneWarnDto.isWarn()){
                                phoneWarnDto.setWarn(true);
                                phoneWarnDto.setFirstWarnTime(new Date());
                                phoneWarnDtos.add(phoneWarnDto);
                                phoneWarnDtoMap.put(dto.getNodeName(),phoneWarnDto);
                                isNeedWarning=true;
                            }else{
                                log.info("已告警:"+dto.getNodeName());
                            }
                        }else{
                            if(oracleScript.contains(dto.getNodeName())){
                                log.info("已报警");
                            }else{
                                needReRun.add(dto);
                            }
                        }
                    }
                    DataworksUtil.insertTaskError(dtos,false);
                    if (needReRun.size()>0){
                        hasRerunMap.putAll(DataworksUtil.reRun(needReRun));
                    }
                }
            }else{
                isNeedWarning=false;
            }
            if(isNeedWarning){
                if (isFirstWarning) {
                    isFirstWarning = false;
                    begin = DateUtil.date();
                    log.info("跑批任务有失败!电话告警");
                    DataworksUtil.phoneWarning(null);
                    isNeedWarning=false;
                } else {
                    //30分钟后依然还有错误 继续电话告警
                    Date end = DateUtil.date();
                    long minutes = DateUtil.between(begin, end, DateUnit.MINUTE);
                    Integer period= config.getInt("warnPeriod",warnPeriod);
                    if (minutes > period) {
                        log.info("跑批任务有失败!电话告警");
                        DataworksUtil.phoneWarning(null);
                        begin =  DateUtil.date();
                        isNeedWarning=false;
                    }
                }
            }
//            if(phoneWarnDtos!=null&&phoneWarnDtos.size()>0){
//                DataworksUtil.phoneWarning(null);
//                log.info("告警脚本:"+JSON.toJSONString(phoneWarnDtos));
//            }
//            告警后 1个小时或2个小时未解决
//            List<PhoneWarnDto> his=new ArrayList<>();
//            for(String key:phoneWarnDtoMap.keySet()){
//                if(phoneWarnDtoMap.get(key).isWarn()){
//                    his.add(phoneWarnDtoMap.get(key));
//                }
//            }
//            if(his!=null&&his.size()>0){
//                List<PhoneWarnDto> firstWarn=his.stream().filter(new Predicate<PhoneWarnDto>() {
//                    @Override
//                    public boolean test(PhoneWarnDto phoneWarnDto) {
//                        boolean flag=false;
//                        if(phoneWarnDto.getFirstWarnTime()!=null){
//                            long minutes = DateUtil.between(phoneWarnDto.getFirstWarnTime(),new Date(), DateUnit.MINUTE);
//                            PhoneWarnDto phoneWarnDto1=phoneWarnDtoMap.get(phoneWarnDto.getNodeName());
//                            boolean firstWarning=phoneWarnDto1.isFirstWarn();
//                            if(firstWarning){
//                                phoneWarnDto1.setFirstWarn(false);
//                                phoneWarnDtoMap.put(phoneWarnDto.getNodeName(),phoneWarnDto1);
//                            }
//                            if(minutes>=60&&firstWarning){
//                                flag=true;
//                            }
//                        }
//                        return flag;
//                    }
//                }).collect(Collectors.toList());
////                List<PhoneWarnDto> secondWarn=his.stream().filter(new Predicate<PhoneWarnDto>() {
////                    @Override
////                    public boolean test(PhoneWarnDto phoneWarnDto) {
////                        boolean flag=false;
////                        if(phoneWarnDto.getFirstWarnTime()!=null){
////                            long minutes = DateUtil.between(phoneWarnDto.getFirstWarnTime(),new Date(), DateUnit.MINUTE);
////                            PhoneWarnDto phoneWarnDto1=phoneWarnDtoMap.get(phoneWarnDto.getNodeName());
////                            boolean secondWarn=phoneWarnDto1.isSecondWarn();
////                            if(secondWarn){
////                                phoneWarnDto1.setSecondWarn(false);
////                                phoneWarnDtoMap.put(phoneWarnDto.getNodeName(),phoneWarnDto1);
////                            }
////                            if(minutes>=120&&secondWarn){
////                                flag=true;
////                            }
////                        }
////
////                        return flag;
////                    }
////                }).collect(Collectors.toList());
//                if(firstWarn!=null&&firstWarn.size()>0){
//                    DataworksUtil.phoneWarning("数据中台报错一个小时未解决","18838098890","17600108115","18838098890");
//                }
////                if(secondWarn!=null&&secondWarn.size()>0){
////                    DataworksUtil.phoneWarning("数据中台报错两个小时未解决","17600108115","18838098890","17600108115");
////                }
//            }

            String cuur=currentHour+":"+currentMinute;
            if(cuur.equals("3:40")){
                log.info("当前未运行数量:"+statusCountDto.getNotRunCount());
                if(statusCountDto.getNotRunCount()>= JobVarUtil.notRunNum){
                    log.info("未运行数量:"+statusCountDto.getNotRunCount());
                    DataworksUtil.phoneWarning("三点数据中台未运行数量为"+statusCountDto.getNotRunCount()+"大于"+JobVarUtil.notRunNum+"个");
                }
            }
            String isDm=config.getStr("isDm","3");
            //文件检测告警 平常3点后未检测到文件后告警 月结时 5点10分后未检测到文件后告警
            boolean isSpecialPeriod = TimeCheckUtil.isMonthEnd(Integer.valueOf(isDm)) || TimeCheckUtil.isMonthBegin(Integer.valueOf(isDm));
            int hour=3;
            int minute=0;
            if(isSpecialPeriod){
                hour=6;
                minute=0;
            }
            boolean isAfterTime=TimeCheckUtil.isAfterTime(hour,minute);
            if(isAfterTime&&!isAllCheck){
                List<InstanceEntityDto> list=DataworksUtil.checkOracleScript(bizDate,endTime);
                if(list!=null&&list.size()>0){
                    // 自动检测文件
                    boolean checkRes=false;
                    for (InstanceEntityDto dto:list){
                        boolean flag=DataworksUtil.checkFile(dto.getNodeName().trim(),bizDate);
                        if(!flag){
                            checkRes=true;
                            break;
                        }
                    }
                    if(checkRes){
                        boolean warning=false;
                        if(oracleBegin!=null){
                            long between = DateUtil.between(oracleBegin, new Date(), DateUnit.MINUTE);
                            if(between>=40){
                                warning=true;
                            }
                        }else {
                            warning=true;
                        }
                        if(warning){
                            DataworksUtil.phoneWarning("数据中台备库还未跑完可能存在异常请及时查看");
                            oracleBegin=new Date();
                        }
                    }
                }else {
                    isAllCheck=true;
                    log.info("数据中台备库跑完");
                }
            }
        } catch (Exception e) {
                log.info("发生异常!电话告警");
                DataworksUtil.phoneWarning("跑批检测任务程序发生异常");
                String stackTrace = ExceptionUtils.getStackTrace(e);
               log.info("异常详情:"+stackTrace);
        }finally {
//            if(dtos!=null&& dtos.size()>0){
//                DataworksUtil.insertTaskError(dtos);
//            }
        }
    }


    private void failureInstances(Integer total) {
        int totalPage=(total+100-1/100);
        for (int i=1;i<=totalPage;i++){
            getData(i);
        }
    }

    private String getData(int page) {
        // 创建DefaultAcsClient实例并初始化
        StringBuffer stringBuffer = new StringBuffer();
        Date newDate = DateUtil.offset(new Date(), DateField.DAY_OF_MONTH, -1);
        String startTime = DateUtil.format(newDate, "yyyy-MM-dd") + " 00:00:00";
        String endTime = DateUtil.format(newDate, "yyyy-MM-dd") + " 00:00:00";
        String time = DateUtil.format(newDate, "yyyyMMdd");
        // 创建API请求并设置参数
        ListInstancesRequest request = new ListInstancesRequest();
        request.setProjectId(10022L); // 替换为你的DataWorks项目名称
        request.setProjectEnv("PROD");
        request.setBeginBizdate(startTime);
        request.setEndBizdate(endTime);
        request.setPageSize(100);
        request.setPageNumber(page);
        // 可以根据需要设置更多参数，如pageNumber、pageSize等
        try {
            // 调用ListInstances方法
            ListInstancesResponse response = client.getAcsResponse(request);
            // 处理响应结果
            if (response != null && response.getSuccess()) {
                stringBuffer.append("第" + page + "页：" + JSON.toJSONString(response) + "\n");
                List<ListInstancesResponse.Data.Instance> instances = response.getData().getInstances();
                instances.forEach(instance -> {
                    if (instance.getStatus().equals("FAILURE")) {
                       log.info("失败实例:"+ instance.getInstanceId()+":实例名称:"+instance.getNodeName());
                    }
                });
            } else {
                log.info("Failed to list instances. Error code: " + response.getErrorCode() + ", Error message: " + response.getErrorMessage());
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return stringBuffer.toString();
    }





    private StatusCountDto getStatusCount() {
        // 创建DefaultAcsClient实例并初始化
        StatusCountDto statusCountDto = null;
        Date newDate = DateUtil.offset(new Date(), DateField.DAY_OF_MONTH, -1);
        String time = DateUtil.format(newDate, "yyyy-MM-dd");
        GetInstanceStatusCountRequest request = new GetInstanceStatusCountRequest();
        request.setProjectId(10022L);
        request.setProjectEnv("PROD");
        request.setBizDate(time);
        try {
            // 调用GetInstanceStatusCount方法
            GetInstanceStatusCountResponse response = null;
            try {
                response = client.getAcsResponse(request);
            } catch (ClientException e) {
                throw new RuntimeException(e);
            }
            // 处理响应结果
            if (response != null) {
                Integer notRunCount = response.getStatusCount().getNotRunCount();
                Integer waitTimeCount = response.getStatusCount().getWaitTimeCount();
                Integer waitResCount = response.getStatusCount().getWaitResCount();
                Integer runningCount = response.getStatusCount().getRunningCount();
                Integer failureCount = response.getStatusCount().getFailureCount();
                Integer successCount = response.getStatusCount().getSuccessCount();
                Integer totalCount = response.getStatusCount().getTotalCount();
                log.info("未运行实例的数量" + notRunCount);
                log.info("等待资源实例的数量" + waitResCount);
                log.info("满足条件开始等待运行的实例数量" + waitTimeCount);
                log.info("运行中的实例的数量" + runningCount);
                log.info("失败的实例的数量" + failureCount);
                log.info("成功的实例的数量" + successCount);
                log.info("总的实例的数量" + totalCount);
                statusCountDto = new StatusCountDto();
                BeanUtils.copyProperties(response.getStatusCount(), statusCountDto);
            } else {
                log.info("Failed to get instance status count. Error code: " + response);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return statusCountDto;
    }

    public static void main(String[] args) {
        String dateStr1 = "2024-06-29 08:16:23";
        Date date1 = DateUtil.parse(dateStr1);

        String dateStr2 = "2024-06-29 23:33:13";
        Date date2 = DateUtil.parse(dateStr2);;

        long betweenDay = DateUtil.between(date1, date2, DateUnit.MINUTE);
        String dateStr = "2024-07-05 00:00:00";
        long timestampFromStr = DateUtil.parse(dateStr).getTime();
        System.out.println(timestampFromStr);
    }

}
